/**
  ******************************************************************************
  * @attention
  * Copyright (c) 2022, SHANGHAI FUDAN MICROELECTRONICS GROUP CO., LTD.(FUDAN MICROELECTRONICS./ FUDAN MICRO.)
  * All rights reserved.
  *
  * Processor:                   FM33FG0xxA
  * http:                        http://www.fmdevelopers.com.cn/
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met
  *
  * 1. Redistributions of source code must retain the above copyright notice,
  *    this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright notice,
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  *
  * 3. Neither the name of the copyright holder nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * 4. To provide the most up-to-date information, the revision of our documents
  *    on the World Wide Web will be the most Current. Your printed copy may be
  *    an earlier revision. To verify you have the latest information avaliable,
  *    refer to: http://www.fmdevelopers.com.cn/.    
  *
  * THIS SOFTWARE IS PROVIDED BY FUDAN MICRO "AS IS" AND ANY EXPRESSED
    ORIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    OF MERCHANTABILITY NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE
    ARE DISCLAIMED.IN NO EVENT SHALL FUDAN MICRO OR ITS CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY WAY OUT OF THE
    USE OF THIS SOFTWARE, EVEN IF ADVISED OFTHE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

#include "crc.h"

#define CRC_TIMEOUT     0xFFFFFFFFUL
#define DATA_LENGTH     8
static uint8_t DATA[DATA_LENGTH] = {0x1CU, 0x1AU, 0x4BU, 0x74U, 0x29U, 0xC0U, 0x22U, 0x33U};


/**
  * @brief  CRC16_CCITT 赛力斯多项式计算
  * @param  puchMsg   输入参数：待计算的数据内容指针地址
  * @param  usDataLen 输入参数：待计算的数据内容长度
  * @retval 输出参数：crc计算结果
  */
unsigned short CRC16_CCITT_FALSE(unsigned char *puchMsg, unsigned int usDataLen)
{
    unsigned char i;
    unsigned short wCRCin = 0xFFFF;
    unsigned short wCPoly = 0x1021;
    unsigned char wChar = 0;
    while(usDataLen--)
    {
        wChar = *(puchMsg++);
        wCRCin ^= (wChar << 8);
        for(i = 0; i < 8; i++)
        {
            if(wCRCin & 0x8000)
            {
                wCRCin = (wCRCin << 1) ^ wCPoly;
            }
            else
            {
                wCRCin = wCRCin << 1;
            }
        }
    }
    return(wCRCin ^ 0x0000);
}

/**
  * @brief  CRC16_CCITT 多项式计算
  * @param  data 输入参数：待计算的数据内容指针地址
  * @param  length 输入参数：待计算的数据内容长度
  * @param  crc_result 输出参数：crc计算结果
  * @retval FL_ErrorStatus枚举值:
  *           -FL_PASS 计算成功
  *           -FL_FAIL 计算失败
  */
__STATIC_INLINE FL_ErrorStatus CRC16_CCITT(uint8_t *data, uint32_t length, uint32_t *crc_result)
{
    uint32_t i;
    uint32_t timeout = 0, busystatus;
    for (i = 0; i < length; i++)
    {
        FL_CRC_WriteData(CRC, *data++);
        do
        {
            busystatus = FL_CRC_IsActiveFlag_Busy(CRC);
            timeout++;

        } while((timeout != CRC_TIMEOUT) && (busystatus != 0x0U));

        if (busystatus != 0x0U) { return FL_FAIL;}
    }
    *crc_result = (uint32_t)(FL_CRC_ReadData(CRC) & 0xFFFFU);
    return FL_PASS;
}


/**
  * @brief  CRC16 CCIT 测试
  * @param  None
  * @retval 返回值：FL_ErrorStatus类型
  *         -FL_PASS 测试成功
  *         -FL_FAIL 测试失败
  */
FL_ErrorStatus CRC16_CCITT_Cal(void)
{
    FL_ErrorStatus status;
    uint32_t result = 0;
    status = CRC16_CCITT(DATA, DATA_LENGTH, &result);

    if ((status == FL_PASS) && (result == 0x6040U))
    {
        return FL_PASS;
    }

    return FL_FAIL;
}


/**
  * @brief  CRC Initialization function
  * @param  void
  * @retval None
  */
void CRC_Init(void)
{
    FL_CRC_InitTypeDef    CRC_InitStruct;

    CRC_InitStruct.initVal         = 0x00000000U;
    CRC_InitStruct.dataWidth       = FL_CRC_DATA_WIDTH_8B;
    CRC_InitStruct.reflectIn       = FL_CRC_INPUT_INVERT_BYTE;
    CRC_InitStruct.reflectOut      = FL_CRC_OUPUT_INVERT_BYTE;
    CRC_InitStruct.xorReg          = 0x00000000U;
    CRC_InitStruct.xorRegState     = FL_DISABLE;
    CRC_InitStruct.polynomialWidth = FL_CRC_POLYNOMIAL_16B;
    CRC_InitStruct.polynomial      = 0x00001021U;
    CRC_InitStruct.calculatMode    = FL_CRC_CALCULATE_SERIAL;

    (void)FL_CRC_Init(CRC, &CRC_InitStruct);
}
